﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace System.Linq
{
    public class ModelExpression
    {
        public class ExpressionItem
        {
            public PropertyInfo Prop { get; private set; }

            public Expression Exp { get; private set; }

            public ExpressionItem(PropertyInfo prop, Expression exp)
            {
                Prop = prop;
                Exp = exp;
            }
        }

        private static readonly ConcurrentDictionary<Type, ModelExpression> Dic = new();

        public ParameterExpression ParamName { get; private set; }

        public List<ExpressionItem> ExpList { get; private set; }

        /// <summary>
        /// 处理实例
        /// </summary>
        /// <typeparam name="TModel">实体类型</typeparam>
        /// <returns></returns>
        public static ModelExpression Instance<TModel>()
        {
            var typeFromHandle = typeof(TModel);
            if (Dic.TryGetValue(typeFromHandle, out ModelExpression value))
                return value;

            lock (typeFromHandle)
            {
                var p = Expression.Parameter(typeFromHandle);
                var expList = new List<ExpressionItem>();
                typeFromHandle.GetProperties().ToList().ForEach(a =>
                {
                    expList.Add(new ExpressionItem(a, Expression.PropertyOrField(p, a.Name)));
                });

                value = new ModelExpression
                {
                    ParamName = p,
                    ExpList = expList
                };
                Dic.TryAdd(typeFromHandle, value);
                return value;
            }
        }
    }
}